package com.ylr.base.common.utils;

import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2021-10-02 11:03:00
 * className: DateUtils 日期工具类
 * version: 1.0
 * description:
 */
public class DateUtils {

    private static final Logger log = LoggerFactory.getLogger(DateUtils.class);

    /**
     * 日期格式化对象
     */
    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 日期对象格式化（yyyy-MM-dd HH:mm:ss）
     * @param date 日期对象
     * @return 格式化对象
     */
    public static String format(Date date) {
        return dateFormat.format(date);
    }

    /**
     * 字符串日期（yyyy-MM-dd HH:mm:ss）格式化成日期对象
     * @param date 字符串日期
     * @return 日期对象
     */
    public static Date parse(String date) {
        try {
            // 日期解析
            return dateFormat.parse(date);
        } catch (ParseException e) {
            log.error("日期字符串解析异常。date={} message={}", date, e.getMessage(), e);
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
    }

    /**
     * 获取系统时间所在日的开始时间（零点零分零秒）
     * 如：
     *  今天是2021-09-05，则获取的结果为：2021-09-05 00:00:00（格式化显示结果）
     *  今天是2021-10-07，则获取的结果为：2021-10-07 00:00:00（格式化显示结果）
     * @return 时间对象
     */
    public static Date startDay() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 0);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 0);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 获取今日结束时间（23点59分59秒999毫秒）
     * 如：
     *  今天是2021-10-10，则获取的结果为：2021-10-10 23:59:59（格式化显示结果）
     *  今天是2021-10-12，则获取的结果为：2021-10-12 23:59:59（格式化显示结果）
     */
    public static Date endDay() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 59);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 59);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 999);

        return calendar.getTime();
    }

    /**
     * 获取下一天的开始时间（零点零分零秒）
     * 如：
     *  今天是2021-09-01，则获取的结果为：2021-09-02 00:00:00（格式化显示结果）
     *  今天是2021-10-07，则获取的结果为：2021-10-08 00:00:00（格式化显示结果）
     *  今天是2021-10-31，则获取的结果为：2021-11-01 00:00:00（格式化显示结果）
     * @return 时间对象
     */
    public static Date nextDayStart() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 0);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 0);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 0);
        // 天数增加一天
        calendar.add(Calendar.DAY_OF_MONTH, 1);

        return calendar.getTime();
    }

    /**
     * 获取系统时间所在月的开始时间（一日零点零分零秒）
     * 如：
     *   今天是2021-10-01，则获取的结果为：2021-10-01 00:00:00（格式化显示结果）
     *   今天是2021-10-30，则获取的结果为：2021-10-01 00:00:00（格式化显示结果）
     *   今天是2021-11-20，则获取的结果为：2021-11-01 00:00:00（格式化显示结果）
     */
    public static Date firstDayOnCurrentMonth() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 0);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 0);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 0);
        // 设置天数值（几号）
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        return calendar.getTime();
    }

    /**
     * 获取系统时间所在月的结束时间（最后一日23点59分59秒）
     * 如：
     *  今天是2022-01-01，则获取的结果为：2021-01-31 23:59:59（格式化显示结果）
     *  今天是2022-02-03，则获取的结果为：2021-02-28 23:59:59（格式化显示结果）
     *  今天是2022-03-28，则获取的结果为：2021-03-31 23:59:59（格式化显示结果）
     * @return 日期对象
     */
    public static Date endTimeOnCurrentMonth() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 0);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 0);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 0);
        // 设置天数值（几号）
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        // 时间增加一个月
        calendar.add(Calendar.MONTH, 1);
        // 时间减少一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);

        return calendar.getTime();
    }

    /**
     * 获取系统时间所在年的开始时间（一月一日零点零分零秒）
     * 如：
     *   今天是2022-01-01，则获取的结果为：2022-01-01 00:00:00（格式化显示结果）
     *   今天是2022-02-20，则获取的结果为：2022-01-01 00:00:00（格式化显示结果）
     *   今天是2022-03-02，则获取的结果为：2022-01-01 00:00:00（格式化显示结果）
     */
    public static Date firstDayOnCurrentYear() {
        // 获取时间对应的日历对象
        Calendar calendar = Calendar.getInstance();
        // 设置月数值（几月）
        calendar.set(Calendar.MONTH, 0);
        // 设置天数值（几号）
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        // 设置小时数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 设置分钟数值
        calendar.set(Calendar.MINUTE, 0);
        // 设置秒数数值
        calendar.set(Calendar.SECOND, 0);
        // 设置毫秒数值
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 根据参数时间对象，获取参数时间’所在日‘的’前一日‘的开始时间和结束时间
     * 如：
     *  今天是2022-02-01，则获取的结果为：2022-01-31 00:00:00、2022-01-31 23:59:59（格式化显示结果）
     *  今天是2022-03-01，则获取的结果为：2022-02-28 00:00:00、2022-02-28 23:59:59（格式化显示结果）
     *  今天是2022-04-25，则获取的结果为：2022-04-24 00:00:00、2022-04-24 23:59:59（格式化显示结果）
     * @param date 时间对象
     * @return 封装两个时间对象的列表[下标0-开始时间 下标1-结束时间]
     */
    public static Date[] getPreDayByDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        // 设置基准时间
        calendar.setTime(date);
        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 时间减少一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        // 获取开始时间
        Date startTime = calendar.getTime();

        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        // 获取结束时间
        Date endTime = calendar.getTime();

        return new Date[] { startTime, endTime };
    }

    /**
     * 根据参数时间对象，获取参数时间’所在月‘的’上一月‘的开始时间和结束时间
     * 如：
     *  今天是2022-02-01，则获取的结果为：2022-01-01 00:00:00、2022-01-31 23:59:59（格式化显示结果）
     *  今天是2022-03-01，则获取的结果为：2022-02-01 00:00:00、2022-02-28 23:59:59（格式化显示结果）
     *  今天是2022-04-25，则获取的结果为：2022-03-01 00:00:00、2022-03-31 23:59:59（格式化显示结果）
     * @param date 时间对象
     * @return 封装两个时间对象的列表[下标0-开始时间 下标1-结束时间]
     */
    public static Date[] getPreMonthByDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        // 设置基准时间
        calendar.setTime(date);
        // 设置日期为1号
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 获取开始时间
        Date startTime = calendar.getTime();

        // 时间增加一个月并减少一天，得到所在月的最后一天
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.DAY_OF_MONTH, -1);

        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        // 获取结束时间
        Date endTime = calendar.getTime();

        return new Date[] { startTime, endTime };
    }

    /**
     * 根据参数时间对象，获取参数时间’所在年‘的’上一年‘的开始时间和结束时间
     * 如：
     *  今天是2020-02-01，则获取的结果为：2019-01-01 00:00:00、2019-12-31 23:59:59（格式化显示结果）
     *  今天是2021-03-01，则获取的结果为：2020-01-01 00:00:00、2020-12-31 23:59:59（格式化显示结果）
     *  今天是2022-04-25，则获取的结果为：2021-01-01 00:00:00、2021-12-31 23:59:59（格式化显示结果）
     * @param date 时间对象
     * @return 封装两个时间对象的列表[下标0-上一年开始时间 下标1-上一年结束时间]
     */
    public static Date[] getPreYearByDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        // 设置基准时间
        calendar.setTime(date);
        // 设置日期为1月1号
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 获取开始时间
        Date startTime = calendar.getTime();

        // 时间增加一年并减少一天，得到所在年的最后一天
        calendar.add(Calendar.YEAR, 1);
        calendar.add(Calendar.DAY_OF_MONTH, -1);

        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        // 获取结束时间
        Date endTime = calendar.getTime();

        return new Date[] { startTime, endTime };
    }

    /**
     * 根据日期对象，获取日期对象当天的结束时间
     * @param date 日期对象
     * @return 当天的结束时间
     */
    public static Date getEndDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        // 设置基准时间
        calendar.setTime(date);
        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);

        return calendar.getTime();
    }

    /**
     * 根据日期对象，获取日期对象当天的开始时间
     * @param date 日期对象
     * @return 当天的结束时间
     */
    public static Date getStartDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        // 设置基准时间
        calendar.setTime(date);
        // 设置小时、分钟、秒和毫秒数值
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

}
